import { log } from "console"
/*--示例一--*/
/**
 * 一个对象只要部署了Iterator接口，我们称这个对象为Iterable对象。
 * ES6规定默认的Iterator接口部署在对象的[Symbol.iterator]属性，
 * 也就是一个对象只要具有[Symbol.iterator]属性(包括通过原型链继承获得)就是Iterable对象。
 * 当使用 for...of遍历该对象时，会自动去寻找Iterator接口。
 * 相应接口数据结构规范：
 * interface Iterable {
 *  [Symbol.iterator]() : Iterator,
 * }
 * interface Iterator {
 * 	next(value?: any) : IterationResult,
 * }
 * interface IterationResult {
 * 	value: any,
 * 	done: boolean,
 * }
 */
function MyIterable(...arr) {
    this.data = arr
}

MyIterable.prototype[Symbol.iterator] = function () {
    let index = 0
    let next = () => {
        return {
            value: this.data[index++] * 2,
            done: index > this.data.length
        }
    }
    return { next }
}

let iterable = new MyIterable(1, 2, 3, 4)
for (let v of iterable) {
    log(v)
}


/*--------示例二：斐波那契数列--------*/
class FibIterator {
    a = 0
    b = 1;

    [Symbol.iterator]() {
        return this
    }

    next() {
        [this.a, this.b] = [this.b, this.a + this.b]
        return { value: this.a, done: false }
    }
}

let fibIter = new FibIterator()[Symbol.iterator]()
log(fibIter.next().value, fibIter.next().value, fibIter.next().value)


/*--------示例三：Range--------*/
class Range {
    constructor(start, end) {
        this.start = start
        this.end = end
    }

    [Symbol.iterator]() {
        let current =  this.start
        return {
            next: () => {
                if (current < this.end) {
                    return { value: current++, done: false }
                }
                return { value: undefined, done: true }
            }
        }
        //return new RangeIterator(this.start, this.end);
    }
}

class RangeIterator {
    constructor(current, end) {
        this.current = current
        this.end = end
    }

    next() {
        if (this.current < this.end) {
            return { value: this.current++, done: false }
        }
        return { value: undefined, done: true }
    }
}

let range = new Range(0, 10)
log(Array.from(range))
log(Array.from(range))
